// -----------------------------
// Author: 		Dhaenens Gert 
// Creation: 	8/4/2013 4:29:38 PM				
// -----------------------------

#ifndef _LuaTable_h
#define _LuaTable_h

#include "ObjectLuaCommon.h"

#include "LuaObject.h"
#include "LuaRef.h"
#include "LuaFunction.h"
#include "LuaClass.h"

namespace ObjectLua
{

	class OBJECTLUA LuaTable : public LuaObject
	{
	public:

		LuaTable();
		LuaTable(Lua* lpLua);
		LuaTable(Lua* lpLua, int refIndex);
		LuaTable(const LuaTable& refLuaTable);
		LuaTable& operator=(const LuaTable& refLuaTable);
		virtual ~LuaTable();

		/*
		//	Add an int to the table
		//	@ name : name of the key
		//	@ value : value of the key
		*/
		void		addInteger(const char* name, int value);
		/*
		//	Add a number to the table
		//	@ name : name of the key
		//	@ value : value of the key
		*/
		void		addNumber(const char* name, double value);
		/*
		//	Add a bool to the table
		//	@ name : name of the key
		//	@ value : value of the key
		*/
		void		addBool(const char* name, bool bValue);
		/*
		//	Add a string to the table
		//	@ name : name of the key
		//	@ value : value of the key
		*/
		void		addString(const char* name, const char* value);
		/*
		//	Add a table to the table
		//	@ name : name of the key
		*/
		LuaTable	addTable(const char* name);
		/*
		//	Add a metatable to the table
		//	@ name : name of the key
		*/
		LuaTable	addMetaTable(const char* name);
		/*
		//	Set a Field from the Stack to this
		//	table
		//	@ name : name of the key
		//	@ idx : index of the key
		*/
		void		setField(const char* name, int idx);
		/*
		//	Add a Function with Closure Object
		//	To the table
		//	@ name : name of the key
		//	@ value : value of the key
		//	@ object : object to be assigned
		*/
		template<typename T>
		void		addClosure(const char* name, int (*value)(lua_State*), T* object);
		/*
		//	Register a Table of Functions
		//	To the Table
		//	@ funcCount : amount of functions
		//	@ functions : function table
		*/
		void		registerFunctions(const int funcCount, LuaReg functions[]);
		/*
		//	Add a CFunction to the table
		//	@ name : name of the function
		//	@ lpFunc : function pointer
		*/
		void		addCFunction(const char* name, int (*lpFunc)(lua_State*));
		/*
		//	Add a function to the table
		//	with 0 arguments
		//	@ name : name of the key
		//	@ value : value of the key
		*/
		template<typename R>
		void		addFunction(const char* name, R (*value)());
		/*
		//	Add a function to the table
		//	with 1 argument
		//	@ name : name of the key
		//	@ value : value of the key
		*/
		template<typename R, typename P0>
		void		addFunction(const char* name, R (*value)(P0));
		/*
		//	Add a function to the table
		//	with 2 arguments
		//	@ name : name of the key
		//	@ value : value of the key
		*/
		template<typename R, typename P0, typename P1>
		void		addFunction(const char* name, R (*value)(P0,P1));
		/*
		//	Add a function to the table
		//	with 3 arguments
		//	@ name : name of the key
		//	@ value : value of the key
		*/
		template<typename R, typename P0, typename P1, typename P2>
		void		addFunction(const char* name, R (*value)(P0,P1,P2));
		/*
		//	Add a function to the table
		//	with 4 arguments
		//	@ name : name of the key
		//	@ value : value of the key
		*/
		template<typename R, typename P0, typename P1, typename P2, typename P3>
		void		addFunction(const char* name, R (*value)(P0,P1,P2,P3));
		/*
		//	Add a function to the table
		//	with 5 arguments
		//	@ name : name of the key
		//	@ value : value of the key
		*/
		template<typename R, typename P0, typename P1, typename P2, typename P3, typename P4>
		void		addFunction(const char* name, R (*value)(P0,P1,P2,P3,P4));
		/*
		//	Add a function to the table
		//	with 6 arguments
		//	@ name : name of the key
		//	@ value : value of the key
		*/
		template<typename R, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5>
		void		addFunction(const char* name, R (*value)(P0,P1,P2,P3,P4,P5));
		/*
		//	Add a function to the table
		//	with 7 arguments
		//	@ name : name of the key
		//	@ value : value of the key
		*/
		template<typename R, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
		void		addFunction(const char* name, R (*value)(P0,P1,P2,P3,P4,P5,P6));
		/*
		//	Add a Class to the Table
		//	@ name : name of the key
		*/
		template<typename Class>
		LuaClass<Class> addClass(const char* name);
		/*
		//	Add an Object to the Table
		//	Class must be Registered
		//	Before adding the Object
		//	@ name : name of the Object
		//	@ metaName : name of the Metatable
		//	@ lpObject : object pointer
		*/
		template<typename Class>
		void		addObject(const char* name, const char* metaName, Class* lpObject);

		/*
		//	Get an integer from the table
		//	@ name : name of the key
		*/
		int			getInteger(const char* name);
		/*
		//	Get a number from the table
		//	@ name : name of the key
		*/
		double		getNumber(const char* name);
		/*
		//	Get a bool from the table
		//	@ name : name of the key
		*/
		bool		getBool(const char* name);
		/*
		//	Get a string from the table
		//	@ name : name of the key
		*/
		const char*	getString(const char* name);
		/*
		//	Get a table from this table
		//	@ name : name of the table
		*/
		LuaTable	getTable(const char* name);
		/*
		//	Get a metatable from this table
		//	@ name : name of the metatable
		*/
		LuaTable	getMetaTable(const char* name);
		/*
		//	Get a field
		//	@ name : name of the field
		*/
		void		getField(const char* name);

		/*
		//	Push this table onto the stack
		*/
		void		push();
	
	private:

		LuaRef		m_Ref;
	};

}

// Function Definitions
#include "LuaTable.inl"

#endif